#include "songmanager.h"
#include <QDebug>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QTimer>
#include <QBuffer>
#include <QDir>
SongManager::SongManager(QObject *parent) : QObject(parent)
{
    initDir();
    initDatabase();
    loadSongs();
//    QTimer* autoStorage = new QTimer(this);
//    connect(autoStorage, &QTimer::timeout, this, &SongManager::storage);
//    autoStorage->start(100000);
}

void SongManager::initDir()
{
    QString cloudMusic = QDir::currentPath() + "/cloudMusic";
    QString image = QDir::currentPath() + "/image";
    if(!QDir().exists(cloudMusic)){
        if(!QDir().mkdir(cloudMusic)){
            qDebug() << "目录创建失败: " << cloudMusic;
        }
    }
    if(!QDir().exists(image)){
        if(!QDir().mkdir(image)){
            qDebug() << "目录创建失败: " << image;
        }
    }
}

void SongManager::initDatabase()
{
    _sqlite = QSqlDatabase::addDatabase("QSQLITE");
    _sqlite.setDatabaseName("songMessageDB.db");
    if(_sqlite.open() == false){
        qDebug() << "sqlite 打开失败 : " << _sqlite.lastError();
        return;
    }

    QSqlQuery song; //"song_id, wangyiyun_id, wangyiyun_url, local_url, name, album, artist, image_url, duration"
    if(song.exec("create table if not exists song("
                        "song_id text primary key not null,"
                        "wangyiyun_id integer,"
                        "wangyiyun_url text,"
                        "local_url text,"
                        "name text,"
                        "album text,"
                        "artist text,"
                        "image_url text,"
                        "duration integer"
                        ")") == false){
        qDebug() << "歌曲表创建失败 : " << song.lastError();
        return;
    }

    QSqlQuery songList; // "list_id, song_id, song_index"
    if(songList.exec("create table if not exists songList("
                     "list_id integer not null,"
                     "song_id text not null,"
                     "song_index integer not null"
                     ")") == false){
        qDebug() << "歌单表创建失败 : " << songList.lastError();
        return;
    }
}

void SongManager::loadSongs()
{
    QSqlQuery songs;
    if (songs.exec("select * from song")) {
        while (songs.next()) {
            QUrl url = songs.value("song_id").toString();

            SongItem* songItem = new SongItem;
            songItem->wangyiyun_id = songs.value("wangyiyun_id").toLongLong();
            songItem->wangyiyun_url = songs.value("wangyiyun_url").toString();
            songItem->local_url = songs.value("local_url").toString();
            songItem->name = songs.value("name").toString();
            songItem->album = songs.value("album").toString();
            songItem->artist = songs.value("artist").toString();
            songItem->image_url = songs.value("image_url").toString();

            songItem->image.load(songs.value("image_url").toString());

            songItem->duration = songs.value("duration").toLongLong();

            _hashSongs[url] = songItem;
        }
    } else {
        qDebug() << "读取歌曲表失败:" << songs.lastError();
    }
    QSqlQuery list;
    QList<int> listId; // 先找id吧
    if (list.exec("select distinct list_id from songList")){
        while(list.next()){
            listId.push_back(list.value("list_id").toInt());
        }
    }
    QString dbg("歌单: ");
    for(auto e : listId) dbg += QString::number(e) + ", ";
    qDebug() << dbg;
    for(auto e : listId){ // 然后通过id找歌单的歌曲
        dbg.clear();
        list.prepare("select song_id, song_index from songList where list_id = ? order by song_index asc");
        list.addBindValue(e);
        dbg = QString::number(e) + "号歌单: ";
        if(list.exec()){
            while(list.next()){
                _hashLists[e].push_back(list.value("song_id").toString()); // 直接加就行,排了序的
                dbg += list.value("song_id").toString() + ", ";
            }
        }
        qDebug() << dbg;
    }

    // 对0号歌单做特殊处理--喜欢歌单
    for(auto& url : _hashLists[0]){
        _hashSongs[url]->isLike = true;
    }

    // 对-1号歌单做特殊处理--存网络url,避免状态不同步
    for(auto& url : _hashLists[-1]){
        _hashSongs[_hashSongs[url]->wangyiyun_url] = _hashSongs[url];
    }
}

void SongManager::addSongItem(SongItem &songItem)
{
    QUrl url = songItem.url();
    if (url.isEmpty()){
        qDebug() << "SongManager: " << songItem.name << " -- url 不存在, 添加失败";
        return;
    }
    if (_hashSongs.count(url)){
        SongItem* curSongItem = _hashSongs[url];
        if(curSongItem->name.isEmpty()) curSongItem->name = songItem.name;
        if(curSongItem->album.isEmpty()) curSongItem->album = songItem.album;
        if(curSongItem->artist.isEmpty()) curSongItem->artist = songItem.artist;
        if(curSongItem->image.isNull()) curSongItem->image = songItem.image;
        if(curSongItem->image_url.isEmpty()) curSongItem->image_url = songItem.image_url;
        if(curSongItem->duration == 0) curSongItem->duration = songItem.duration;
        if(curSongItem->wangyiyun_url.isEmpty()) curSongItem->wangyiyun_url = songItem.wangyiyun_url;
        if(curSongItem->wangyiyun_id == 0) curSongItem->wangyiyun_id = songItem.wangyiyun_id;
        if(curSongItem->local_url.isEmpty()) curSongItem->local_url = songItem.local_url;
        songItem = *curSongItem;
        qDebug() << "SongManager: " << songItem.name << " -- 已存在, 更新成功";
    } else {
        _hashSongs[url] = new SongItem(songItem);
        qDebug() << "SongManager: " << songItem.name << " -- 未存在, 添加成功";
    }
}

bool SongManager::getSongItem(SongItem *songItem)
{
    QUrl url = songItem->url();
    if (_hashSongs.count(url)){
        *songItem = *_hashSongs[url];
        return true;
    }
    if (url.isEmpty()){
        qDebug() << "SongManager::getSongItem : url.isEmpty";
    } else {
        qDebug() << "SongManager::getSongItem : url 没找到, 需添加";
    }
    return false;
}

bool SongManager::getSongItem(SongItem *songItem, const QUrl& url)
{
    if (_hashSongs.count(url)){
        *songItem = *_hashSongs[url];
        return true;
    }
    qDebug() << "SongManager::getSongItem : url.isEmpty";
    return false;
}

void SongManager::download(qint64 id)
{
    QString urlStr = "http://music.163.com/song/media/outer/url?id=" + QString::number(id) + ".mp3";
    SongItem* song = _hashSongs[urlStr];
    QString path = song->name + " - " + song->artist + ".mp3";
    path.replace('/', ',');
    path = "cloudMusic/" + path;

    song->local_url = path;  //  壳没换,内容换了,之后网络url自动对应过来,播放时用的实际是本地url
    _hashSongs[path] = song;

    addToList(path, -1);
    emit downloaded(urlStr, path);
}

const SongItem &SongManager::getSongItem(const QUrl& url)
{
    return *_hashSongs[url];
}

bool SongManager::exist(const QUrl& url)
{
    return _hashSongs.count(url) != 0;
}

void SongManager::addToList(const QUrl& url, int listIndex)
{
//    emit addToList(url, listIndex);
    _hashLists[listIndex].push_back(url);
}

void SongManager::play(const QUrl& url, bool isPlay)
{
    _hashSongs[url]->isPlaying = isPlay;
    emit played(url, isPlay);
}

void SongManager::like(const QUrl& url, bool isLike)
{
    if (_hashSongs.count(url)){
        _hashSongs[url]->isLike = isLike;
        emit liked(url, isLike);
    } else {
        qDebug() << "url " << url << ", 未存在于SongManager";
    }
}

void SongManager::updateSongList(int listId, const QList<QUrl> &songList)
{
    qDebug() << "updateSongList";
    _hashLists[listId] = songList;
}

const QList<QUrl>& SongManager::getSongList(int listId)
{
    return _hashLists[listId];
}

void SongManager::addSongToList(int listId, const QUrl &url)
{
    _hashLists[listId].push_back(url);
}

void SongManager::deleteSongFromList(int listId, const QUrl &url)
{
    _hashLists[listId].removeAll(url);
}

void SongManager::storage()
{
    if (_sqlite.transaction()){
        QSqlQuery clear;
        if(!clear.exec("delete from song where 1")){
            qDebug() << "清空表失败:" << clear.lastError();
            _sqlite.rollback();
            return;
        }
        if(!clear.exec("delete from songList where 1")){
            qDebug() << "清空表失败:" << clear.lastError();
            _sqlite.rollback();
            return;
        }

        QSet<QUrl> songs; // 存歌曲信息,由于歌单间歌曲可能重复,用set简单去下重
        QSqlQuery storageSong;
        storageSong.prepare("insert into song (song_id, wangyiyun_id, wangyiyun_url, local_url, name, album, artist, image_url, duration)"
                            "values (?,?,?,?,?,?,?,?,?)");
        qDebug() << "开始存入数据库";
        for(auto it = _hashLists.begin(); it != _hashLists.end(); it++){
            int listIndex = it.key();

            int size = it.value().size();
            qDebug() << "下标为" << listIndex << "的歌单有" << size << "首歌曲";
            // 现在存歌单
            QSqlQuery storageList;
            storageList.prepare("insert into songList (list_id, song_id, song_index)"
                                "values (?, ?, ?)");
            QVariantList list_id, song_id, song_index;
            for(int i = 0; i < size; i++){
                songs.insert(it.value()[i]);
                SongItem* song = _hashSongs[it.value()[i]];
                qDebug() << "保存歌曲 : " << song->name << ", 下标" << i;
                list_id << listIndex;
                song_id << song->url();
                song_index << i;
            }
            storageList.addBindValue(list_id);
            storageList.addBindValue(song_id);
            storageList.addBindValue(song_index);
            if(!storageList.execBatch()){
                qDebug() << "歌曲信息保存出错" << storageList.lastError();
                _sqlite.rollback();
                return;
            }
        }

        // 遍历完所有歌单了,需要的歌的信息就都拿到了
        // 现在开始存歌的信息
        QVariantList song_id, wangyiyun_id, wangyiyun_url, local_url, name, album, artist, image_url, duration;
        for(auto song_url : songs){
            SongItem* song = _hashSongs[song_url];
            song_id << song->url();
            wangyiyun_id << song->wangyiyun_id;
            wangyiyun_url << song->wangyiyun_url;
            local_url << song->local_url;
            name << song->name;
            album << song->album;
            artist << song->artist;

            // 本来打算直接往数据库里存图片二进制数据的,不过太慢了
            // 那就存路径吧,图片存文件里
            QString fileName;
            if(song->album.size()) fileName = song->album + ".png";
            else fileName = song->name + " - " + song->artist + ".png";
            for(auto c : {'<', '>', ':', '"', '/', '\\', '|', '?', '*'})
                fileName.replace(c, ',');
            fileName = "image/" + fileName;
            if(!QDir().exists(fileName)){
                if(false == song->image.save(fileName, "PNG")){
                    qDebug() << "图片保存失败" << fileName;
                }
            } else {
                qDebug() << "图片存在,不用保存";
            }
            image_url << fileName;
            duration << song->duration;
        }
        storageSong.addBindValue(song_id);
        storageSong.addBindValue(wangyiyun_id);
        storageSong.addBindValue(wangyiyun_url);
        storageSong.addBindValue(local_url);
        storageSong.addBindValue(name);
        storageSong.addBindValue(album);
        storageSong.addBindValue(artist);
        storageSong.addBindValue(image_url);
        storageSong.addBindValue(duration);
        // 多个记录,一条语句插入,提高效率
        if(storageSong.execBatch() == false){
            qDebug() << "歌曲信息保存出错" << storageSong.lastError();
            _sqlite.rollback();
            qDebug() << "共" << songs.size() << "首歌曲:";
            for(auto e : songs) qDebug() << e;
            return;
        }
        _sqlite.commit();
    } else {
        qDebug() << "事务启动! 失败...";
    }
}

SongManager* SongManager::_songManager = nullptr;
